/*
 * TruthTable.cpp
 *
 *  Created on: Mar 8, 2012
 *      Author: luiz
 */


#include <sstream>
#include <math.h>
#include <iostream>

#include "TruthTable.h"


TruthTable::TruthTable(int num_inputs, int num_outputs):num_inputs_(num_inputs),num_outputs_(num_outputs)
{

    for (int i = 0; i < num_inputs; ++i) {
        std::stringstream oss;
        oss << "INPUT#" << i ;
        truth_table_inputs.push_back(std::pair<std::string,std::vector<int> >(oss.str(),std::vector<int>()));
        oss.clear();
    }
    for (int i = 0; i < num_outputs; ++i) {
        std::stringstream oss;
        oss << "OUTPUT#" << i ;
        truth_table_outputs.push_back(std::pair<std::string,std::vector<int> >(oss.str(),std::vector<int>()));
        oss.clear();
    }

}

TruthTable::TruthTable(const TruthTable & truthtable)
{

    num_inputs_ = truthtable.num_inputs_;
    num_outputs_ = truthtable.num_outputs_;
    truth_table_inputs = truthtable.truth_table_inputs;
    truth_table_outputs = truthtable.truth_table_outputs;


}

TruthTable & TruthTable::operator =(const TruthTable & truthtable)
{
    if(this != & truthtable){
        num_inputs_ = truthtable.num_inputs_;
        num_outputs_ = truthtable.num_outputs_;
        truth_table_inputs = truthtable.truth_table_inputs;
        truth_table_outputs = truthtable.truth_table_outputs;
    }
    return *this;

}

std::string TruthTable::print_truth_table() const
{
    std::stringstream oss;
    for (int j = 0; j < num_inputs_; ++j) {
        oss  << truth_table_inputs[j].first << "\t";
    }
    for (int j = 0; j < num_outputs_; ++j) {
        oss  << truth_table_outputs[j].first << "\t";
    }
    oss << "\n";
    for (int i = 0; i < this->num_entrys(); ++i) {
        for (int j = 0; j < num_inputs_+num_outputs_; ++j) {
            if(j < num_inputs_){
                oss << truth_table_inputs[j].second[i] << "\t";
            } else {
                oss << truth_table_outputs[j-num_inputs_].second[i] << "\t";
            }
        }
        oss << "\n";
    }
    return oss.str();
}

int TruthTable::get_input_entry_value(int input_id, int input_entry)
{
    return truth_table_inputs[input_id].second[input_entry];
}

void TruthTable::set_input_entry_value(int input_id, int input_entry, int value)
{
    truth_table_inputs[input_id].second[input_entry]= value;
}

void TruthTable::set_input_entry_name(int input_id, std::string input_name)
{
    truth_table_inputs[input_id].first = input_name;
}

std::string TruthTable::get_input_name_by_id(int input_id)
{
    return  truth_table_inputs[input_id].first;
}

int TruthTable::get_output_entry_value(int output_id, int output_entry)
{
    return truth_table_outputs[output_id].second[output_entry];
}

void TruthTable::set_output_entry_value(int output_id, int output_entry, int value)
{
    truth_table_outputs[output_id].second[output_entry] = value;
}

void TruthTable::set_output_entry_name(int output_id, std::string output_name)
{
    truth_table_outputs[output_id].first = output_name;
}

std::string TruthTable::get_output_name_by_id(int output_id)
{
    return truth_table_outputs[output_id].first;
}

int TruthTable::num_inputs()
{
    return truth_table_inputs.size();
}

int TruthTable::num_outputs()
{
    return truth_table_outputs.size();
}

std::vector<int> TruthTable::get_list_input_id()
{
    std::vector<int> id_return;
    for (std::map<std::string,int>::iterator it = input_name_id.begin(); it!=input_name_id.end(); ++it)
    {
        id_return.push_back(it->second);
    }
    return id_return;
}

std::vector<int> TruthTable::get_list_output_id()
{
    std::vector<int> id_return;
    for (std::map<std::string,int>::iterator it = output_name_id.begin(); it!=output_name_id.end(); ++it)
    {
        id_return.push_back(it->second);
    }
    return id_return;
}

int TruthTable::num_entrys() const
{
    return truth_table_inputs[0].second.size();
}

int TruthTable::get_output_entry_by_name(std::string name)
{
    int id_return  =-1;
    for (int i = 0; i < (int)truth_table_inputs.size(); ++i) {
        if(truth_table_outputs[i].first == name){
            id_return = i;
            break;
        }
    }
    return id_return;
}

int TruthTable::get_output_occurrences_by_value(int value)
{
    int count =0;
    for (int i = 0; i < (int)truth_table_outputs.size(); ++i) {
        for (int j = 0; j < (int)truth_table_outputs[i].second.size(); ++j) {
            if(value == truth_table_outputs[i].second[j]){
                count++;
            }
        }
    }
    return count;
}

void TruthTable::add_input_entry(int input_id, int entry_value)
{
    truth_table_inputs[input_id].second.push_back(entry_value);
}

void TruthTable::add_output_entry(int output_id, int entry_value)
{
    truth_table_outputs[output_id].second.push_back(entry_value);
}

TruthTable::~TruthTable()
{

}

